#ifndef ASYNCWEBSERVERHANDLERIMPL_H_
#define ASYNCWEBSERVERHANDLERIMPL_H_

#if CONFIG_ASYNCWEBSERVER_REGEX
#include <regex>
#endif

// 静态资源请求处理器
class AsyncStaticWebHandler : public AsyncWebHandler {
private:
    bool    m_getFile(AsyncWebServerRequest* req);
    bool    m_fileExists(AsyncWebServerRequest* req, const std::string &path);
    uint8_t m_countBits(const uint8_t value) const;
    bool    FILE_IS_REAL(const char* path) const;
protected:
    // FS m_fs; 文件系统实例，实现根据请求中的URI到该实例中获取文件并返回
    std::string  m_uri;              // 处理器绑定的URI前缀
    std::string  m_path;             // 文件系统中的根路径（将URI映射到实际路径）
    std::string  m_default_file;     // 请求目录时返回的默认文件
    std::string  m_cache_control;    // 设置HTTP响应头，控制客户端缓存行为
    std::string  m_last_modified;    // 设置HTTP响应头Last-Modified,用于条件请求
    AwsTemplateProcessor    m_callback; // 模板处理函数，用于发送文件前动态修改文件
    bool    m_isDir;            // 标记处理器处理的URI是否为目录
    bool    m_gzipFirst;        // 是否优先查找gzip文件
    uint8_t m_gzipStats;        // 统计最近8次GZIP文件查找结查（用于动态调整查找顺序）
public:
    AsyncStaticWebHandler(const char* uri, const char* path, const char* cache_control);
    virtual bool canHandle(AsyncWebServerRequest* req) override final;
    virtual void handleRequest(AsyncWebServerRequest* req) override final;
    AsyncStaticWebHandler &setIsDir(bool isDir)
    {
        m_isDir = isDir;
        return *this;
    }
    AsyncStaticWebHandler &setDefaultFile(const char* filename)
    {
        m_default_file = std::string(filename);
        return *this;
    }
    AsyncStaticWebHandler &setCacheControl(const char* cache_control)
    {
        m_cache_control = std::string(cache_control);
        return *this;
    }
    AsyncStaticWebHandler &setLastModified(const char* last_modified)
    {
        m_last_modified = std::string(last_modified);
        return *this;
    }
    AsyncStaticWebHandler &setLastModified(struct tm* last_modified);
    AsyncStaticWebHandler &setTemplateProcessor(AwsTemplateProcessor cb)
    {
        m_callback = cb;
        return *this;
    }

};

class AsyncCallbackWebHandler : public AsyncWebHandler {
protected:
    std::string m_uri;                          // 待处理的URI路径
    WebRequestMethodComposite   m_method;       // 支持的HTTP方法
    ArRequestHandlerFunction    m_onRequest;    // 请求处理回调函数
    ArUploadHandlerFunction     m_onUpload;     // 文件上传回调函数
    ArBodyHandlerFunction       m_onBody;       // 请求体处理回调函数
    bool    m_isRegex;                          // 标计URI是否为正则表达式
public:
    AsyncCallbackWebHandler()
        : m_uri()
        , m_method(HTTP_ANY)
        , m_onRequest(nullptr)
        , m_onUpload(nullptr)
        , m_onBody(nullptr)
    {}
    void setUri(const std::string &uri)
    {
        m_uri = uri;
        m_isRegex = uri.starts_with("^") && uri.ends_with("$");
    }
    void setMethod(WebRequestMethodComposite m)
    {
        m_method = m;
    }
    void onRequest(ArRequestHandlerFunction fn)
    {
        m_onRequest = fn;
    }
    void onUpload(ArUploadHandlerFunction fn)
    {
        m_onUpload = fn;
    }
    void onBody(ArBodyHandlerFunction fn)
    {
        m_onBody = fn;
    }

    /// @brief 确定当前请求能否由该处理器处理
    /// @param req
    /// @return
    virtual bool canHandle(AsyncWebServerRequest* req) override final
    {
        // 处理器设置有问题，返回false
        if (!m_onRequest || m_uri.length() == 0) {
            return false;
        }
        // 请求的方法不在处理器支持的方法范围内，返回true
        if (!(m_method & req->method())) {
            return false;
        }
#if CONFIG_ASYNCWEBSERVER_REGEX
        if (m_isRegex) {
            std::regex pattern(m_uri.c_str());
            std::smatch matches;
            std::string s(req->url().c_str());
            if (std::regex_search(s, matches.size(), pattern)) {
                for (size_t i = 1; i < matches.size(); ++i) {
                    req->m_addPathParam(matches[i].str().c_str());
                }
            } else {
                return false;
            }
        } else
#endif
            // 通配符模式：包含特定的结尾
            if (m_uri.starts_with("/*.")) {
                std::string uriTemplate = std::string(m_uri);
                uriTemplate = uriTemplate.substr(uriTemplate.find_last_of("."));
                if (!req->url().ends_with(uriTemplate)) {
                    return false;
                }
            } else
                // 通配符模式：以特定字符串开头
                if (m_uri.ends_with("*")) {
                    std::string uriTemplate = std::string(m_uri);
                    uriTemplate = uriTemplate.substr(0, uriTemplate.length() - 1);
                    if (! req->url().starts_with(uriTemplate)) {
                        return false;
                    }
                } else
                    // 完全匹配
                    if (m_uri != req->url() && !req->url().starts_with(m_uri + "/")) {
                        return false;
                    }
        req->addInterestingHeader("ANY");
        return true;
    }

    /// @brief 根据情况对请求进行认证后调用Request回调函数
    /// @param req
    virtual void handleRequest(AsyncWebServerRequest* req) override final
    {
        if ((m_username != "" && m_password != "") && !req->authenticate(m_username.c_str(), m_password.c_str())) {
            return req->requestAuthentication();
        }
        if (m_onRequest) {
            m_onRequest(req);
        } else {
            req->send(500);
        }
    }

    /// @brief 根据情况对请求进行认证后调用Upload回调函数
    /// @param req
    /// @param filename
    /// @param index
    /// @param data
    /// @param len
    /// @param final
    virtual void handleUpload(AsyncWebServerRequest* req, const std::string &filename, size_t index, uint8_t *data, size_t len, bool final) override final
    {
        if ((m_username != "" && m_password != "") && !req->authenticate(m_username.c_str(), m_password.c_str())) {
            return req->requestAuthentication();
        }
        if (m_onUpload) {
            m_onUpload(req, filename, index, data, len, final);
        }
    }

    /// @brief 根据情况对请求进行认证后调用Body回调函数
    /// @param req
    /// @param data
    /// @param len
    /// @param index
    /// @param total
    virtual void handleBody(AsyncWebServerRequest* req, uint8_t *data, size_t len, size_t index, size_t total) override final
    {
        if ((m_username != "" && m_password != "") && !req->authenticate(m_username.c_str(), m_password.c_str())) {
            return req->requestAuthentication();
        }
        if (m_onBody) {
            m_onBody(req, data, len, index, total);
        }
    }

    /// @brief 标识处理器是否存在用户自定义处理逻辑
    virtual bool isRequestHandlerTrivial() override final
    {
        return m_onRequest != nullptr ? false : true;
    }
};

#endif